home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume90 / unix / uucp106d / part10 < prev    next >
Encoding:
Text File  |  1990-06-28  |  26.8 KB  |  1,174 lines

  1. Path: xanth!cs.odu.edu!Amiga-Request
  2. From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v90i188: UUCP 1.06D - UNIX compatible uucp/news/mail system, Part10/12
  5. Message-ID: <12979@xanth.cs.odu.edu>
  6. Date: 28 Jun 90 12:23:31 GMT
  7. Sender: news@cs.odu.edu
  8. Reply-To: Matt Dillon <@uunet.uu.net:overload!dillon>
  9. Lines: 1160
  10. Approved: tadguy@cs.odu.edu (Tad Guy)
  11. X-Mail-Submissions-To: Amiga@cs.odu.edu
  12. X-Post-Discussions-To: comp.sys.amiga
  13.  
  14. Submitted-by: Matt Dillon <@uunet.uu.net:overload!dillon>
  15. Posting-number: Volume 90, Issue 188
  16. Archive-name: unix/uucp-1.06d/part10
  17.  
  18. #!/bin/sh
  19. # This is a shell archive.  Remove anything before this line, then unpack
  20. # it by saving it into a file and typing "sh file".  To overwrite existing
  21. # files, type "sh file -c".  You can also feed this as standard input via
  22. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  23. # will see the following message at the end:
  24. #        "End of archive 10 (of 12)."
  25. # Contents:  uucp2/src/sendmail/sendmail.c
  26. # Wrapped by tadguy@xanth on Thu Jun 28 08:21:35 1990
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f 'uucp2/src/sendmail/sendmail.c' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'uucp2/src/sendmail/sendmail.c'\"
  30. else
  31. echo shar: Extracting \"'uucp2/src/sendmail/sendmail.c'\" \(24049 characters\)
  32. sed "s/^X//" >'uucp2/src/sendmail/sendmail.c' <<'END_OF_FILE'
  33. X
  34. X/*
  35. X *  SENDMAIL / RMAIL
  36. X *
  37. X *  $Header: Beta:src/uucp/src/sendmail/RCS/sendmail.c,v 1.1 90/02/02 12:15:01 dillon Exp Locker: dillon $
  38. X *
  39. X *  (C) Copyright 1989-1990 by Matthew Dillon,  All Rights Reserved.
  40. X *
  41. X *  SENDMAIL <file -f from -t to -s subject -c cc -b bcc -r
  42. X *  RMAIL user
  43. X *
  44. X *  Example:    Sendmail <datafile -froot
  45. X *
  46. X *  From: line is automatically added but can be overriden by a From:
  47. X *  header in the file.  stdin is made up of a list of headers, a blank
  48. X *  line, and then data until EOF.
  49. X *
  50. X *  the -r option tells sendmail that this is incomming mail.
  51. X *  If av[0] begins with an 'r' for RMail instead of an 's' for
  52. X *  Sendmail, then the rmail argument format is used (rmail user),
  53. X *  as well as forcing -r.
  54. X */
  55. X
  56. X#include "defs.h"
  57. X
  58. X#include <fcntl.h>
  59. X#include <log.h>
  60. X#include <time.h>
  61. X#include <pwd.h>
  62. X
  63. Xtypedef struct List    LIST;
  64. Xtypedef struct Node    NODE;
  65. X
  66. XIDENT(".06");
  67. X
  68. XLocal    void Usage(void);
  69. XLocal    int brk(void);
  70. XLocal    NODE *MakeNode(LIST *, char *);
  71. XLocal    void MakeToFixNode(LIST *, char *, char *);
  72. XLocal    void fixCallBack(char *);
  73. XLocal    void IntegrateHeader(char *, short);
  74. XLocal    void FromFixup(LIST *);
  75. XLocal    void ToFixup(LIST *);
  76. XLocal    void MakeToAddrNode(LIST *, char *);
  77. XLocal    FILE *SendMailTo(LIST *, FILE *);
  78. XLocal    FILE *OneMailTo(char *, FILE *);
  79. XLocal    FILE *OneMailToPipe(char *, FILE *);
  80. XLocal    FILE *OneMailToUser(char *, FILE *);
  81. XLocal    FILE *OneMailToFile(char *, FILE *);
  82. XLocal    FILE *OneMailToUUCP(char *, char *, FILE *);
  83. XLocal    void DumpHeaderInfo(FILE *, int, int, int);
  84. XLocal    void DumpHeader(FILE *, char *, LIST *);
  85. XLocal    NODE *FindHeader(char *);
  86. XLocal    void DumpCombineHeader(FILE *, char *, LIST *);
  87. XLocal    char *atime(time_t *);
  88. XLocal    int GetHourOffset(char *);
  89. XLocal    void PostPend(char *, int);
  90. XLocal    int EmptyList(LIST *);
  91. X
  92. X
  93. X#define RCVR_UUCP    1
  94. X#define RCVR_SENDMAIL    2
  95. X
  96. Xchar    *UserName;
  97. Xchar    *RealName;
  98. Xchar    *NodeName;
  99. Xchar    *DomainName;
  100. Xchar    *TimeZoneName;    /*  All caps, ex: PST             */
  101. Xchar    *DefaultNode;    /*  for addr formats we don't understand */
  102. XLIST    RecvList;    /*  Received:        */
  103. XLIST    FromList;    /*  last one rules  */
  104. XLIST    ToList;     /*  To:         */
  105. XLIST    CcList;     /*  Cc:         */
  106. XLIST    BccList;    /*  Bcc:        */
  107. XLIST    XccList;    /*  list of actual mail to be sent  */
  108. XLIST    SubjList;    /*  Subject:        */
  109. XLIST    HdrList;    /*  other headers not specifically parsed */
  110. Xchar    ScrBuf[1024];
  111. Xchar    ScrBuf2[1024];
  112. Xchar    TempFileBuf[256];
  113. Xint    Seq;        /*  UUCP sequence no    */
  114. Xchar    Notify;
  115. Xchar    ROpt;        /*  Receive-Mail flag    */
  116. Xstatic char OrigFromLine[512];
  117. Xstatic char FromLine[512];  /*    'From ' line, if ROpt   */
  118. X
  119. X
  120. X
  121. Xmain(ac, av)
  122. Xchar *av[];
  123. X{
  124. X    short isRMail = 0;
  125. X    short isSendMail = 1;
  126. X    FILE *fi;
  127. X
  128. X    onbreak(brk);
  129. X
  130. X    NewList(&RecvList);
  131. X    NewList(&FromList);
  132. X    NewList(&ToList);
  133. X    NewList(&CcList);
  134. X    NewList(&BccList);
  135. X    NewList(&XccList);
  136. X    NewList(&SubjList);
  137. X    NewList(&HdrList);
  138. X
  139. X    UserName = GetUserName();
  140. X    RealName = GetRealName();
  141. X
  142. X    if (UserName == NULL) {
  143. X    puts("Sendmail: UserName config entry not found!");
  144. X    ulog(0, "UserName config missing");
  145. X    exit(1);
  146. X    }
  147. X    if (RealName == NULL) {
  148. X    puts("Sendmail: RealName config entry not found!");
  149. X    ulog(0, "RealName config missing");
  150. X    exit(1);
  151. X    }
  152. X
  153. X    NodeName = FindConfig("NodeName");
  154. X    if (NodeName == NULL) {
  155. X    puts("Sendmail: NodeName config entry not found!");
  156. X    ulog(0, "NodeName config missing");
  157. X    exit(1);
  158. X    }
  159. X    DomainName = FindConfig("DomainName");
  160. X    if (DomainName == NULL) {
  161. X    puts("Sendmail: DomainName config entry not found! using .UUCP");
  162. X    DomainName = ".UUCP";
  163. X    }
  164. X    DefaultNode = FindConfig("DefaultNode");
  165. X    TimeZoneName = FindConfig("TimeZone");
  166. X
  167. X    LoadAliases();
  168. X
  169. X    {
  170. X    char *ptr = av[0] + strlen(av[0]);
  171. X
  172. X    /*
  173. X     *  Skip path
  174. X     */
  175. X
  176. X    while (ptr >= av[0] && *ptr != ':' && *ptr != '/')
  177. X        --ptr;
  178. X    ++ptr;
  179. X
  180. X    if (*ptr == 'r' || *ptr == 'R') {
  181. X        isRMail = 1;
  182. X        isSendMail = 0;
  183. X    }
  184. X    }
  185. X
  186. X    if (isRMail) {
  187. X    char *addr = (ac == 2) ? av[1] : "Mailer-Daemon";
  188. X
  189. X    MakeNode(&BccList, addr);
  190. X    UserName = "postmaster";    /*  XXX  */
  191. X    RealName = "Mr.Amiga";      /*  XXX  */
  192. X    ROpt = 1;            /*    no header processing */
  193. X    }
  194. X    if (isSendMail) {
  195. X    short i;
  196. X    char *arg;
  197. X    for (i = 1; i < ac; ++i) {
  198. X        arg = av[i];
  199. X        if (*arg != '-')
  200. X        Usage();
  201. X        switch(arg[1]) {
  202. X        case 'f':
  203. X        UserName = av[i+1];
  204. X        sprintf(ScrBuf, "%s@%s%s", UserName, NodeName, DomainName);
  205. X        MakeNode(&FromList, ScrBuf);
  206. X        ++i;
  207. X        break;
  208. X        case 'r':
  209. X        RealName = av[++i];
  210. X        break;
  211. X        case 't':
  212. X        MakeNode(&ToList, av[++i]);
  213. X        break;
  214. X        case 'c':
  215. X        MakeNode(&CcList, av[++i]);
  216. X        break;
  217. X        case 'b':
  218. X        MakeNode(&BccList, av[++i]);
  219. X        break;
  220. X        case 's':
  221. X        MakeNode(&SubjList, av[++i]);
  222. X        break;
  223. X        case 'r':
  224. X        ++ROpt;
  225. X        break;
  226. X        default:
  227. X        Usage();
  228. X        }
  229. X    }
  230. X    }
  231. X
  232. X    /*
  233. X     *    Read headers from input file.  Headers are not necessarily
  234. X     *    contained on a single line.  Maximum 4096 chars per header.
  235. X     */
  236. X
  237. X    if (ROpt) {
  238. X    fgets(ScrBuf, sizeof(ScrBuf), stdin);
  239. X    strcpy(OrigFromLine, ScrBuf);
  240. X    if (strncmp(ScrBuf, "From ", 5) != 0) {
  241. X        ulog(-1, "Receive mail, expected 'From ', got %s", ScrBuf);
  242. X    }
  243. X    strcpy(FromLine, "From ");
  244. X    PostPend(ScrBuf + 5, 1);
  245. X
  246. X    while (fgets(ScrBuf, sizeof(ScrBuf), stdin) && strncmp(ScrBuf, ">From ", 6) == 0) {
  247. X        strcpy(OrigFromLine, ScrBuf + 1);
  248. X        PostPend(ScrBuf + 6, 1);
  249. X    }
  250. X    strcpy(ScrBuf2, OrigFromLine + 5);
  251. X    PostPend(ScrBuf2, 0);
  252. X    } else {
  253. X    ScrBuf[0] = '\n';
  254. X    fgets(ScrBuf, sizeof(ScrBuf), stdin);
  255. X    }
  256. X    {
  257. X    static char Hdr[4096];
  258. X    short i = 0;        /*  index into Hdr  */
  259. X
  260. X    while (ScrBuf[0] != '\n') {
  261. X        char *ptr = ScrBuf;
  262. X        while (*ptr && *ptr != ' ' && *ptr != 9 && *ptr != ':')
  263. X        ++ptr;
  264. X        if (*ptr == ':') {  /*  found new header */
  265. X        if (i)          /*  Dump old header  */
  266. X            IntegrateHeader(Hdr, i);
  267. X        strcpy(Hdr, ScrBuf);
  268. X        i = strlen(Hdr);
  269. X        } else {        /*  append to existing header    */
  270. X        if (i == 0)
  271. X            puts("Expected a Header!");
  272. X        strcpy(Hdr + i, ScrBuf);
  273. X        i = i + strlen(Hdr + i);
  274. X        }
  275. X
  276. X        if (fgets(ScrBuf, sizeof(ScrBuf), stdin) == NULL)
  277. X        ScrBuf[0] = '\n';
  278. X    }
  279. X    if (i)
  280. X        IntegrateHeader(Hdr, i);
  281. X
  282. X    if (ScrBuf[0] != '\n') {
  283. X        puts("sendmail: no mail");
  284. X        ulog(0, "No Mail");
  285. X        exit(1);
  286. X    }
  287. X    }
  288. X
  289. X    /*
  290. X     *    Parse & fixup each To:, Cc:, and Bcc: field.
  291. X     *
  292. X     *    From:    we add the personal info arg from the password file
  293. X     *    To:    we expand any aliases
  294. X     */
  295. X
  296. X    if (ROpt == 0)
  297. X    FromFixup(&FromList);
  298. X    if (ROpt) {
  299. X    ToFixup(&BccList);
  300. X    } else {
  301. X    ToFixup(&ToList);
  302. X    ToFixup(&CcList);
  303. X    ToFixup(&BccList);
  304. X    }
  305. X
  306. X    /*
  307. X     *    If no Subject: field add a dummy one
  308. X     */
  309. X
  310. X    if (EmptyList(&SubjList))
  311. X    MakeNode(&SubjList, "");
  312. X
  313. X    if (EmptyList(&FromList)) {
  314. X    sprintf(ScrBuf, "%s@%s%s", UserName, NodeName, DomainName);
  315. X    MakeNode(&FromList, ScrBuf);
  316. X    }
  317. X
  318. X    fi = SendMailTo(&XccList, stdin);
  319. X    if (fi && fi != stdin)
  320. X    fclose(fi);
  321. X    if (TempFileBuf[0])
  322. X    remove(TempFileBuf);
  323. X    UnLockFiles();
  324. X
  325. X    /*
  326. X     *    Notify if T:MailRdy does not exist (created by us, deleted by
  327. X     *    notify when notify exits).  Prevents running multiple notifies.
  328. X     */
  329. X
  330. X    if (Notify) {
  331. X    int fd = open("T:MailRdy", O_RDONLY);
  332. X    if (fd < 0) {
  333. X        char *cmd;
  334. X
  335. X
  336. X        if (cmd = FindConfig(MAILREADYCMD)) {
  337. X        fd = open("T:MailRdy", O_CREAT|O_TRUNC, 0666);
  338. X        if (fd >= 0)
  339. X            close(fd);
  340. X        sprintf(ScrBuf, "Run %s -x T:MailRdy", cmd);
  341. X        Execute(ScrBuf, NULL, NULL);
  342. X        }
  343. X    } else {
  344. X        close(fd);
  345. X    }
  346. X    }
  347. X    return(0);
  348. X}
  349. X
  350. Xvoid
  351. XUsage()
  352. X{
  353. X    printf(
  354. X    "Sendmail -f user [-t address -c address -b address -s subject -r]\n"
  355. X    "RMail user\n"
  356. X    );
  357. X}
  358. X
  359. Xint
  360. Xbrk()
  361. X{
  362. X    return(0);
  363. X}
  364. X
  365. X/*
  366. X *  Strips string and creates named node which is appended to the
  367. X *  given list.
  368. X */
  369. X
  370. XNODE *
  371. XMakeNode(list, str)
  372. XLIST *list;
  373. Xchar *str;
  374. X{
  375. X    NODE *node;
  376. X    char *ptr;
  377. X
  378. X    while (*str == ' ' || *str == 9)
  379. X    ++str;
  380. X    for (ptr = str + strlen(str); ptr >= str && (*ptr == ' ' || *ptr == 9); --ptr);
  381. X    ++ptr;
  382. X    *ptr = 0;
  383. X    node = malloc(sizeof(NODE) + strlen(str) + 1);
  384. X    node->ln_Name = (char *)(node + 1);
  385. X    strcpy(node->ln_Name, str);
  386. X    AddTail(list, node);
  387. X    return(node);
  388. X}
  389. X
  390. X/*
  391. X *
  392. X */
  393. X
  394. Xvoid
  395. XMakeToFixNode(list, str, send)
  396. XLIST *list;
  397. Xchar *str;
  398. Xchar *send;
  399. X{
  400. X    char *ptr;
  401. X    short len;
  402. X    short c;
  403. X    void fixCallBack();
  404. X
  405. X    while (str < send && (*str == ' ' || *str == 9))
  406. X    ++str;
  407. X    for (ptr = send - 1; ptr >= str && (*ptr == ' ' || *ptr == 9); --ptr);
  408. X    ++ptr;
  409. X
  410. X    len = ptr - str;
  411. X    if (len < 0)
  412. X    return;
  413. X
  414. X    /*
  415. X     *    str[0..len-1]
  416. X     */
  417. X
  418. X    c = str[len];
  419. X    str[len] = 0;
  420. X
  421. X    if (ROpt) {     /*  disallow remote asking for special options */
  422. X    ulog(-1, "Received mail for %s", str);
  423. X    if (str[0] == '>' || str[0] == '<' || str[0] == '|' || str[0] == ':' || str[0] == '/') {
  424. X        ulog(-1, "SendMail, bad user %s", str);
  425. X        return;
  426. X    }
  427. X    }
  428. X
  429. X    {
  430. X    NODE *node = malloc(sizeof(NODE) + strlen(str) + 1);
  431. X
  432. X    node->ln_Name = (char *)(node + 1);
  433. X    strcpy(node->ln_Name, str);
  434. X    AddTail(list, node);
  435. X    }
  436. X
  437. X    UserAliasList(str, fixCallBack);    /*  from lib/alias.c    */
  438. X    str[len] = c;
  439. X}
  440. X
  441. Xvoid
  442. XfixCallBack(user)
  443. Xchar *user;
  444. X{
  445. X    NODE    *node;
  446. X
  447. X    if (user[0] == '<') {
  448. X    FILE *fi = fopen(user + 1, "r");
  449. X    char *buf = malloc(256);
  450. X
  451. X    if (fi == NULL) {
  452. X        ulog(-1, "Unable to open < file %s", user + 1);
  453. X        return;
  454. X    }
  455. X    while (fgets(buf, 256, fi)) {
  456. X        short i = 0;
  457. X        short j;
  458. X        while (buf[i] == ' ' || buf[i] == 9)
  459. X        ++i;
  460. X        if (buf[i] == 0 || buf[i] == '\n')
  461. X        continue;
  462. X        for (j = i; buf[j] && buf[j] != '\n' && buf[j] != ' ' && buf[j] != 9; ++j);
  463. X        buf[j] = 0;
  464. X        UserAliasList(buf, fixCallBack);
  465. X    }
  466. X    fclose(fi);
  467. X    free(buf);
  468. X    return;
  469. X    }
  470. X
  471. X    ulog(-1, "Sendmail, Sending mail to %s", user);
  472. X
  473. X    if (user[0] == '\\')
  474. X    ++user;
  475. X
  476. X    node = malloc(sizeof(NODE) + strlen(user) + 1);
  477. X    node->ln_Name = (char *)(node + 1);
  478. X    strcpy(node->ln_Name, user);
  479. X    AddTail(&XccList, node);
  480. X}
  481. X
  482. X
  483. X/*
  484. X *  Integrates a header
  485. X */
  486. X
  487. Xvoid
  488. XIntegrateHeader(hdr, len)
  489. Xchar *hdr;
  490. Xshort len;
  491. X{
  492. X    if (hdr[len-1] == '\n')     /*  strip trailing newline  */
  493. X    hdr[len-1] = 0;
  494. X
  495. X    if (strncmp(hdr, "From:", 5) == 0) {
  496. X    MakeNode(&FromList, hdr + 5);
  497. X    return;
  498. X    }
  499. X    if (strncmp(hdr, "To:", 3) == 0) {
  500. X    MakeNode(&ToList, hdr + 3);
  501. X    return;
  502. X    }
  503. X    if (strncmp(hdr, "Cc:", 3) == 0) {
  504. X    MakeNode(&CcList, hdr + 3);
  505. X    return;
  506. X    }
  507. X    if (strncmp(hdr, "Bcc:", 4) == 0) {
  508. X    MakeNode(&BccList, hdr + 4);
  509. X    return;
  510. X    }
  511. X    if (strncmp(hdr, "Subject:", 8) == 0) {
  512. X    MakeNode(&SubjList, hdr + 8);
  513. X    return;
  514. X    }
  515. X    if (strncmp(hdr, "Received:", 9) == 0) {
  516. X    MakeNode(&RecvList, hdr + 9);
  517. X    return;
  518. X    }
  519. X    MakeNode(&HdrList, hdr);
  520. X}
  521. X
  522. X/*
  523. X *  Adds (personal info) to FromList based on passwd entry or, if
  524. X *  that is not available, from the Config entry 'RealName' or
  525. X *  ENV:REALNAME (env:REALNAME takes precedence)
  526. X */
  527. X
  528. Xvoid
  529. XFromFixup(list)
  530. XLIST *list;
  531. X{
  532. X    NODE *node;
  533. X    NODE *nn;
  534. X    LIST tmpList;
  535. X
  536. X    NewList(&tmpList);
  537. X
  538. X    while (node = RemHead(list)) {
  539. X    /*
  540. X     *  FIXME.  Fix getpwnam() and use pw_gecos entry.
  541. X     */
  542. X    nn = malloc(sizeof(NODE) + strlen(node->ln_Name) + strlen(RealName) + 16);
  543. X    nn->ln_Name = (char *)(nn + 1);
  544. X    sprintf(nn->ln_Name, "%s (%s)", node->ln_Name, RealName);
  545. X    free(node);
  546. X    AddTail(&tmpList, nn);
  547. X    }
  548. X    while (node = RemHead(&tmpList))
  549. X    AddTail(list, node);
  550. X}
  551. X
  552. X/*
  553. X *  Converts an unparsed list of names into a list of single address
  554. X *  fields, removing any personal idents from the entries.  These will
  555. X *  be recombined after processing when the data file is written out.
  556. X *
  557. X *  Also expands sendmail aliases (UULIB:Aliases) (HACK)
  558. X */
  559. X
  560. Xvoid
  561. XToFixup(list)
  562. XLIST *list;
  563. X{
  564. X    NODE *node;
  565. X    LIST tmpList;
  566. X
  567. X    NewList(&tmpList);
  568. X
  569. X    while (node = RemHead(list)) {
  570. X    char *str = node->ln_Name;
  571. X    char *ptr;
  572. X
  573. X    while (*str) {      /*  breakup fields by newline or comma */
  574. X        for (ptr = str; *ptr && *ptr != '\n' && *ptr != ','; ++ptr);
  575. X        MakeToAddrNode(&tmpList, str);
  576. X        str = ptr;
  577. X        while (*str == '\n' || *str == ',' || *str == ' ' || *str == 9)
  578. X        ++str;
  579. X    }
  580. X    free(node);
  581. X    }
  582. X    while (node = RemHead(&tmpList))
  583. X    AddTail(list, node);
  584. X}
  585. X
  586. X/*
  587. X *  Extracts a single name / address (comma or newline delimited)
  588. X *  field and creates a new node.
  589. X */
  590. X
  591. Xvoid
  592. XMakeToAddrNode(list, str)
  593. XLIST *list;
  594. Xchar *str;
  595. X{
  596. X    char *p1, *p2;
  597. X    short ns = 0;    /*  non-whitespace encountered */
  598. X
  599. X    for (p1 = str; *p1 && *p1 != ',' && *p1 != '\n'; ++p1) {
  600. X    if (*p1 == '(') {   /*  addr (name) OR (name) addr */
  601. X        if (ns) {       /*  addr (name) */
  602. X        MakeToFixNode(list, str, p1);
  603. X        } else {
  604. X        while (*p1 && *p1 != ',' && *p1 != '\n' && *p1 != ')')
  605. X            ++p1;
  606. X        if (*p1 == ')') {
  607. X            for (p2 = p1 + 1; *p2 && *p2 != ',' && *p2 != '\n'; ++p2);
  608. X            MakeToFixNode(list, p1 + 1, p2);
  609. X        }
  610. X        }
  611. X        return;
  612. X    }
  613. X
  614. X    if (*p1 == '<') {   /*  <addr>  */
  615. X        for (p2 = p1 + 1; *p2 && *p2 != ',' && *p2 != '\n' && *p2 != '>'; ++p2);
  616. X        if (*p2 == '>')
  617. X        MakeToFixNode(list, p1 + 1, p2);
  618. X        return;
  619. X    }
  620. X    if (*p1 != ' ' && *p1 != 9)
  621. X        ns = 1;
  622. X    }
  623. X    MakeToFixNode(list, str, p1);
  624. X}
  625. X
  626. X
  627. X/*
  628. X *  Send mail to <recipeant>
  629. X *
  630. X *    -Local mail
  631. X *    -Machine path (UUCP)
  632. X */
  633. X
  634. XFILE *
  635. XSendMailTo(list, fi)
  636. XLIST *list;
  637. XFILE *fi;
  638. X{
  639. X    NODE *node;
  640. X
  641. X    for (node = list->lh_Head; node != (NODE *)&list->lh_Tail; node = node->ln_Succ)
  642. X    fi = OneMailTo(node->ln_Name, fi);
  643. X    return(fi);
  644. X}
  645. X
  646. XFILE *
  647. XOneMailTo(toaddr, rfi)
  648. Xchar *toaddr;
  649. XFILE *rfi;
  650. X{
  651. X    short i;
  652. X    char c;
  653. X    static char ToAddr[512];
  654. X    static char Buf[512];
  655. X    static char typeBuf[16];
  656. X    static char classBuf[16];
  657. X    static char addrBuf[128];
  658. X
  659. X    if (toaddr[0] == '|')       /*  pipe through command    */
  660. X    return(OneMailToPipe(toaddr + 1, rfi));
  661. X    if (toaddr[0] == '>')       /*  copy to file            */
  662. X    return(OneMailToFile(toaddr + 1, rfi));
  663. X
  664. X    strncpy(ToAddr, toaddr, sizeof(ToAddr));
  665. X    ToAddr[sizeof(ToAddr) - 1] = 0;
  666. X
  667. Xloop:
  668. X    for (i = 0; c = ToAddr[i]; ++i) {
  669. X    if (c == '!' || c == '%' || c == '@' || c == ':')
  670. X        break;
  671. X    }
  672. X    if (c == 0)                 /*  local name  */
  673. X    return(OneMailToUser(ToAddr, rfi));
  674. X
  675. X    /*
  676. X     *    Non-Local mail
  677. X     */
  678. X
  679. X    i = ParseAddress(ToAddr, Buf, strlen(ToAddr));
  680. X    if (DomainLookup(Buf, strlen(Buf), typeBuf, classBuf, addrBuf)) {
  681. X    printf("type %s class %s addr %s\n", typeBuf, classBuf, addrBuf);
  682. X    printf("buf %s\n", Buf);
  683. X
  684. X    /*
  685. X     *  Note distinction between mail destination and mail forwarder.
  686. X     *  mail destination removes the first machine from the rmail line
  687. X     *  mail forwarder does NOT
  688. X     */
  689. X
  690. X    if (strcmpi(classBuf, "UU") == 0) {
  691. X        if (strcmpi(typeBuf, "MD") == 0)
  692. X        return(OneMailToUUCP(addrBuf, Buf + i + 1, rfi));
  693. X        else
  694. X        return(OneMailToUUCP(addrBuf, Buf, rfi));
  695. X    } else if (strcmpi(classBuf, "LL") == 0) {  /*  local mail, loop */
  696. X        for (i = 0; Buf[i] && Buf[i] != '!'; ++i);
  697. X        if (Buf[i] == 0) {
  698. X        strcpy(Buf + i, "postmaster");
  699. X        --i;
  700. X        }
  701. X        strcpy(ToAddr, Buf + i + 1);
  702. X        goto loop;
  703. X    } else {
  704. X        ulog(-1, "Unsupported domain class: %s", classBuf);
  705. X        printf("Unsupported domain class: %s\n", classBuf);
  706. X    }
  707. X    return(rfi);
  708. X    } else {
  709. X    ulog(-1, "Could not find domain for %s, no mail sent", Buf);
  710. X    printf("Unable to send mail to %s\n", Buf);
  711. X    return(rfi);
  712. X    }
  713. X}
  714. X
  715. X
  716. XFILE *
  717. XOneMailToPipe(toaddr, rfi)
  718. Xchar *toaddr;
  719. XFILE *rfi;
  720. X{
  721. X    FILE *fi;
  722. X    char *ptr;
  723. X    static long pos;
  724. X
  725. X    if (TempFileBuf[0] == 0) {
  726. X    strcpy(TempFileBuf, TmpFileName("T:pipe"));
  727. X    fi = fopen(TempFileBuf, "w");
  728. X    if (fi == NULL) {
  729. X        ulog(-1, "Unable to open temp file %s for command: %s", TempFileBuf, toaddr);
  730. X        return(rfi);
  731. X    }
  732. X    DumpHeaderInfo(fi, RCVR_SENDMAIL, 0, 1);
  733. X    pos = ftell(fi);
  734. X    while (fgets(ScrBuf, sizeof(ScrBuf), rfi))
  735. X        fputs(ScrBuf, fi);
  736. X    fclose(fi);
  737. X    }
  738. X    strcpy(ScrBuf, toaddr);
  739. X
  740. X    ptr = toaddr;
  741. X    if (strncmpi(toaddr, "run", 3) == 0) {
  742. X    ptr += 3;
  743. X    while (*ptr == ' ' || *ptr == 9)
  744. X        ++ptr;
  745. X    }
  746. X    while (*ptr && *ptr != ' ' && *ptr != 9)
  747. X    ++ptr;
  748. X
  749. X    if (*ptr == 0)
  750. X    strcat(ScrBuf, " ");
  751. X    sprintf(ScrBuf + (ptr - toaddr + 1), "<%s %s", TempFileBuf, ptr);
  752. X    if (Execute(ScrBuf, NULL, NULL) == 0)
  753. X    ulog(-1, "Couldn't execute %s", ScrBuf);
  754. X
  755. X    fi = fopen(TempFileBuf, "r");
  756. X    if (fi) {
  757. X    if (rfi != stdin)
  758. X        fclose(rfi);
  759. X    rfi = fi;
  760. X    fseek(rfi, pos, 0);
  761. X    } else {
  762. X    ulog(-1, "Couldn't reopen temp '%s', mail failed!", TempFileBuf);
  763. X    rfi = stdin;
  764. X    }
  765. X    return(rfi);
  766. X}
  767. X
  768. XFILE *
  769. XOneMailToUser(toaddr, rfi)
  770. Xchar *toaddr;
  771. XFILE *rfi;
  772. X{
  773. X    ++Notify;
  774. X    strcpy(ScrBuf, MakeConfigPath(UUMAIL, toaddr));
  775. X    return(OneMailToFile(ScrBuf, rfi));
  776. X}
  777. X
  778. XFILE *
  779. XOneMailToFile(tofile, rfi)
  780. Xchar *tofile;
  781. XFILE *rfi;
  782. X{
  783. X    FILE *fo;
  784. X    static char DataFile[128];
  785. X    long pos;
  786. X
  787. X    strcpy(DataFile, tofile);
  788. X
  789. X    LockFile(DataFile);
  790. X    fo = fopen(DataFile, "a");
  791. X    if (fo == NULL) {
  792. X    strcpy(DataFile, "T:MailOverflow");
  793. X    fo = fopen(DataFile, "a");
  794. X    if (fo)
  795. X        ulog(-1, "Could not append to %s, appending to %s", tofile, DataFile);
  796. X    else
  797. X        ulog(-1, "Can't append to anywhere! (%s)", tofile);
  798. X    }
  799. X    if (fo) {
  800. X    DumpHeaderInfo(fo, RCVR_SENDMAIL, 0, 1);
  801. X    pos = ftell(fo);
  802. X    if (ROpt) {
  803. X        if (fgets(ScrBuf, sizeof(ScrBuf), rfi))
  804. X        fputs(ScrBuf, fo);
  805. X    }
  806. X    while (fgets(ScrBuf, sizeof(ScrBuf), rfi)) {
  807. X        if (ScrBuf[0] == 'F' && strncmp(ScrBuf, "From ", 5) == 0)
  808. X        strins(ScrBuf, " ");
  809. X        fputs(ScrBuf, fo);
  810. X    }
  811. X    fclose(fo);
  812. X    if (rfi != stdin)
  813. X        fclose(rfi);
  814. X    rfi = fopen(DataFile, "r");
  815. X    fseek(rfi, pos, 0);
  816. X    }
  817. X    UnLockFile(DataFile);
  818. X    return(rfi);
  819. X}
  820. X
  821. XFILE *
  822. XOneMailToUUCP(toaddr, skipaddr, rfi)
  823. Xchar *toaddr;
  824. Xchar *skipaddr;
  825. XFILE *rfi;
  826. X{
  827. X    static char ExecFile[128];
  828. X    static char XExecFile[128];
  829. X    static char CommandFile[128];
  830. X    static char DataFile[128];
  831. X    static char DestNode[256];
  832. X    /*static char ToAddr[256];*/
  833. X    FILE *fi;
  834. X    int seq;
  835. X    long pos;
  836. X    short i;
  837. X    short ai;
  838. X    char *spoolDir = strdup(MakeConfigPath(UUSPOOL, ""));
  839. X
  840. X    /*
  841. X     *    If the destination node
  842. X     */
  843. X
  844. X    strcpy(DestNode, toaddr);
  845. X
  846. X    ai = -1;
  847. X    for (i = 0; DestNode[i]; ++i) {
  848. X    /*
  849. X     *  Remember index for additional paths
  850. X     */
  851. X
  852. X    if (DestNode[i] == '!') {
  853. X        DestNode[i] = 0;
  854. X        ai = i + 1;
  855. X        break;
  856. X    }
  857. X
  858. X    /*
  859. X     *  Cut off machine name at 7 chars and ignore any domain
  860. X     *  info.
  861. X     */
  862. X
  863. X    if (i == 7 || DestNode[i] == '.')
  864. X        DestNode[i] = 0;
  865. X    }
  866. X
  867. X    Seq = seq = GetSequence(4);
  868. X
  869. X#define FOFF    strlen(spoolDir)
  870. X
  871. X    sprintf(ExecFile,   "%sD.%sX%04d", spoolDir, DestNode, seq++);
  872. X    sprintf(XExecFile,  "%sX.%sX%04d", spoolDir, DestNode, seq++);
  873. X    sprintf(CommandFile,"%sC.%sA%04d", spoolDir, DestNode, seq++);
  874. X    sprintf(DataFile,   "%sD.%sB%04d", spoolDir, DestNode, seq);
  875. X
  876. X    LockFile(CommandFile);
  877. X    LockFile(DataFile);
  878. X
  879. X    /*
  880. X     *    Note, cannot run uuxqt from sendmail as uuxqt may call
  881. X     *    sendmail!
  882. X     */
  883. X
  884. X    if (strncmp(DestNode, NodeName, 7) == 0)
  885. X    fi = fopen(XExecFile, "w");
  886. X    else
  887. X    fi = fopen(ExecFile, "w");
  888. X
  889. X    if (fi == NULL)
  890. X    goto fail;
  891. X
  892. X    fprintf(fi, "U %s\n", UserName);
  893. X    fprintf(fi, "F %s\n", DataFile + FOFF);
  894. X    fprintf(fi, "I %s\n", DataFile + FOFF);
  895. X    if (ai >= 0)
  896. X    fprintf(fi, "C rmail %s!%s\n", DestNode + ai, skipaddr);
  897. X    else
  898. X    fprintf(fi, "C rmail %s\n", skipaddr);
  899. X    fclose(fi);
  900. X
  901. X    if (strncmp(DestNode, NodeName, 7)) {
  902. X    fi = fopen(CommandFile, "w");
  903. X    if (fi == NULL)
  904. X        goto fail;
  905. X
  906. X    fprintf(fi, "S %s %s %s - %s 0666\n", DataFile + FOFF, DataFile + FOFF, UserName, DataFile + FOFF);
  907. X    fprintf(fi, "S %s %s %s - %s 0666\n", ExecFile + FOFF, XExecFile + FOFF, UserName, ExecFile + FOFF);
  908. X    fclose(fi);
  909. X    }
  910. X
  911. X    fi = fopen(DataFile, "w");
  912. X    if (fi == NULL)
  913. X    goto fail;
  914. X
  915. X    DumpHeaderInfo(fi, RCVR_UUCP, 1, 0);
  916. X    pos = ftell(fi);
  917. X
  918. X    if (ROpt) {
  919. X    if (fgets(ScrBuf, sizeof(ScrBuf), rfi))
  920. X        fputs(ScrBuf, fi);
  921. X    }
  922. X    while (fgets(ScrBuf, sizeof(ScrBuf), rfi)) {
  923. X    if (ScrBuf[0] == 'F' && strncmp(ScrBuf, "From ", 5) == 0)
  924. X        strins(ScrBuf, " ");
  925. X    fputs(ScrBuf, fi);
  926. X    }
  927. X    fclose(fi);
  928. X    if (rfi != stdin)
  929. X    fclose(rfi);
  930. X    fi = fopen(DataFile, "r");
  931. X    fseek(fi, pos, 0);
  932. X
  933. X    UnLockFile(CommandFile);
  934. X    UnLockFile(DataFile);
  935. X
  936. X    free(spoolDir);
  937. X
  938. X    return(fi);
  939. Xfail:
  940. X    UnLockFile(CommandFile);
  941. X    UnLockFile(DataFile);
  942. X
  943. X    free(spoolDir);
  944. X    puts("Fail");
  945. X    ulog(-1, "Output failed %s", CommandFile);
  946. X    return(rfi);
  947. X}
  948. X
  949. Xvoid
  950. XDumpHeaderInfo(fi, rcvr, resend, local)
  951. XFILE *fi;
  952. Xint rcvr, resend, local;
  953. X{
  954. X    char *source;
  955. X    time_t t;
  956. X
  957. X    time(&t);
  958. X
  959. X    /*
  960. X     *    Write header info
  961. X     */
  962. X
  963. X    if (rcvr == RCVR_UUCP)
  964. X    source = "AmigaUUCP";
  965. X    else
  966. X    source = "Sendmail";
  967. X
  968. X    if (ROpt) {
  969. X    if (resend)
  970. X        fprintf(fi, "%s %s remote from %s\n", FromLine, atime(&t), NodeName);
  971. X    else
  972. X        fprintf(fi, "%s %s\n", FromLine, atime(&t));
  973. X    } else {
  974. X    if (local)
  975. X        fprintf(fi, "From %s %s\n", UserName, atime(&t));
  976. X    else
  977. X        fprintf(fi, "From %s %s remote from %s\n", UserName, atime(&t), NodeName);
  978. X    }
  979. X    fprintf(fi, "Received: by %s%s (1.05D/Amiga)\n\tid AA%05d; %s\n",
  980. X    NodeName, DomainName, Seq, atime(&t)
  981. X    );
  982. X    DumpHeader(fi, "Received:", &RecvList);
  983. X    if (ROpt == 0) {
  984. X    time_t t2 = t + 3600 * GetHourOffset(TimeZoneName);
  985. X    struct tm *ut;
  986. X
  987. X    if (FindHeader("Date:") == NULL)
  988. X        fprintf(fi, "Date: %s\n", atime(&t));
  989. X    ut = localtime(&t2);
  990. X    fprintf(fi, "Message-Id: <%02d%02d%02d%02d%02d.AA%05d@%s%s>\n",
  991. X        ut->tm_year % 100, ut->tm_mon + 1, ut->tm_mday, ut->tm_hour, ut->tm_min,
  992. X        Seq, NodeName, DomainName
  993. X    );
  994. X    }
  995. X
  996. X    /*
  997. X     *    From:, To:, Cc:, Subject: (Bcc: never written to header),
  998. X     *    and any other header fields
  999. X     */
  1000. X
  1001. X    DumpHeader(fi, NULL, &HdrList);
  1002. X    DumpHeader(fi, "From:", &FromList);
  1003. X    DumpCombineHeader(fi, "To:", &ToList);
  1004. X    if (!EmptyList(&CcList))
  1005. X    DumpCombineHeader(fi, "Cc:", &CcList);
  1006. X    DumpHeader(fi, "Subject:", &SubjList);
  1007. X
  1008. X    fprintf(fi, "\n");
  1009. X}
  1010. X
  1011. Xvoid
  1012. XDumpHeader(fi, field, list)
  1013. XFILE *fi;
  1014. Xchar *field;
  1015. XLIST *list;
  1016. X{
  1017. X    NODE *node;
  1018. X
  1019. X    for (node = list->lh_Head; node != (NODE *)&list->lh_Tail; node = node->ln_Succ) {
  1020. X    if (field)
  1021. X        fprintf(fi, "%s %s\n", field, node->ln_Name);
  1022. X    else
  1023. X        fprintf(fi, "%s\n", node->ln_Name);
  1024. X    }
  1025. X}
  1026. X
  1027. XNODE *
  1028. XFindHeader(field)
  1029. Xchar *field;
  1030. X{
  1031. X    NODE *node;
  1032. X    short len = strlen(field);
  1033. X
  1034. X    for (node = HdrList.lh_Head; node != (NODE *)&HdrList.lh_Tail; node = node->ln_Succ) {
  1035. X    if (strncmp(node->ln_Name, field, len) == 0)
  1036. X        return(node);
  1037. X    }
  1038. X    return(NULL);
  1039. X}
  1040. X
  1041. Xvoid
  1042. XDumpCombineHeader(fi, field, list)
  1043. XFILE *fi;
  1044. Xchar *field;
  1045. XLIST *list;
  1046. X{
  1047. X    NODE *node;
  1048. X    short ci = 0;
  1049. X
  1050. X    fprintf(fi, "%s ", field);
  1051. X    for (node = list->lh_Head; node != (NODE *)&list->lh_Tail; node = node->ln_Succ) {
  1052. X    if (ci && ci + strlen(node->ln_Name) > 70) {
  1053. X        fprintf(fi, ",\n\t");
  1054. X        ci = 0;
  1055. X    }
  1056. X    if (ci)
  1057. X        fprintf(fi, ", ");
  1058. X    fprintf(fi, "%s", node->ln_Name);
  1059. X    ci += strlen(node->ln_Name) + 2;
  1060. X    }
  1061. X    fprintf(fi, "\n");
  1062. X}
  1063. X
  1064. Xchar *
  1065. Xatime(pt)
  1066. Xtime_t *pt;
  1067. X{
  1068. X    static char buf[40];
  1069. X    static char *mo[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  1070. X                "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  1071. X            };
  1072. X    static char *dow[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
  1073. X    struct tm *ut = localtime(pt);
  1074. X
  1075. X    sprintf(buf, "%s, %d %s %02d %02d:%02d:%02d %s",
  1076. X    dow[ut->tm_wday], ut->tm_mday, mo[ut->tm_mon],
  1077. X    ut->tm_year % 100, ut->tm_hour, ut->tm_min, ut->tm_sec,
  1078. X    TimeZoneName
  1079. X    );
  1080. X    return(buf);
  1081. X}
  1082. X
  1083. Xint
  1084. XGetHourOffset(tz)
  1085. Xchar *tz;
  1086. X{
  1087. X    short i;
  1088. X
  1089. X    static struct {
  1090. X    char *Name;
  1091. X    short Hours;
  1092. X    } TZAry[] = {
  1093. X    "GMT",  0,
  1094. X    "UT",   0,
  1095. X    "PST",  8,
  1096. X    "MST",  7,
  1097. X    "CST",  6,
  1098. X    "EST",  5,
  1099. X    "AST",  4,
  1100. X    "PDT",  7,
  1101. X    "MDT",  6,
  1102. X    "CDT",  5,
  1103. X    "EDT",  4,
  1104. X    "ADT",  3,
  1105. X    NULL, 0
  1106. X    };
  1107. X    for (i = 0; TZAry[i].Name; ++i) {
  1108. X    if (strncmp(tz, TZAry[i].Name, 3) == 0)
  1109. X        return((int)TZAry[i].Hours);
  1110. X    }
  1111. X    ulog(-1, "Unknown Timezone: %s", tz);
  1112. X    printf("Unknown Timezone: %s", tz);
  1113. X    return(6);
  1114. X}
  1115. X
  1116. Xvoid
  1117. XPostPend(str, frend)
  1118. Xchar *str;
  1119. Xint frend;
  1120. X{
  1121. X    char *ptr;
  1122. X    if (frend) {
  1123. X    ptr = str + strlen(str);
  1124. X    while (ptr > str && *ptr != ' ' && *ptr != 9) {
  1125. X        if (*ptr == '\n')
  1126. X        *ptr = 0;
  1127. X        --ptr;
  1128. X    }
  1129. X    str = ptr + 1;
  1130. X    }
  1131. X    for (ptr = str; *ptr && *ptr != ' ' && *ptr != 9 && *ptr != '\n'; ++ptr);
  1132. X    if (frend)
  1133. X    *ptr++ = '!';
  1134. X    *ptr = 0;
  1135. X    for (ptr = FromLine + 5; *ptr && *ptr != ' ' && *ptr != 9; ++ptr);
  1136. X    strins(ptr, str);
  1137. X}
  1138. X
  1139. XEmptyList(list)
  1140. XLIST *list;
  1141. X{
  1142. X    if (list->lh_Head == (NODE *)&list->lh_Tail)
  1143. X    return(1);
  1144. X    return(0);
  1145. X}
  1146. X
  1147. END_OF_FILE
  1148. if test 24049 -ne `wc -c <'uucp2/src/sendmail/sendmail.c'`; then
  1149.     echo shar: \"'uucp2/src/sendmail/sendmail.c'\" unpacked with wrong size!
  1150. fi
  1151. # end of 'uucp2/src/sendmail/sendmail.c'
  1152. fi
  1153. echo shar: End of archive 10 \(of 12\).
  1154. cp /dev/null ark10isdone
  1155. MISSING=""
  1156. for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
  1157.     if test ! -f ark${I}isdone ; then
  1158.     MISSING="${MISSING} ${I}"
  1159.     fi
  1160. done
  1161. if test "${MISSING}" = "" ; then
  1162.     echo You have unpacked all 12 archives.
  1163.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1164. else
  1165.     echo You still need to unpack the following archives:
  1166.     echo "        " ${MISSING}
  1167. fi
  1168. ##  End of shell archive.
  1169. exit 0
  1170. -- 
  1171. Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
  1172. Mail comments to the moderator at <amiga-request@cs.odu.edu>.
  1173. Post requests for sources, and general discussion to comp.sys.amiga.
  1174.